package com.example.websocket_demo.websocketController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.websocket_demo.service.message.MessageService;
import com.example.websocket_demo.service.user.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/*
* @ServerEndpoint(value = "/websocket")：设置WebSocket请求路径
* @Component：注册到spring容器中
* */
@ServerEndpoint(value = "/websocket/{userId}")
@Component
public class MyWebSocket {

    private static UserService userService;
    // 注入的时候，给类的 service 注入
    @Autowired
    public void setUserService(UserService userService) {
        MyWebSocket.userService = userService;
    }
    private static MessageService messageService;
    // 注入的时候，给类的 service 注入
    @Autowired
    public void setMessageService(MessageService messageService) {
        MyWebSocket.messageService = messageService;
    }
    /*
    * 静态全局变量（类变量）：
    *       webSocketMap：保存所有在线socket连接
    *       count：记录当前在线数目
    * 类成员变量：
    *       session：当前连接（每个websocket连入都会创建一个MyWebSocket实例）
    *       log：日志
    * 类成员方法：
    *       onOpen()：处理连接建立
    *       onMessage()：接受消息
    *       onError()：处理错误
    *       onClose()：处理连接关闭
    *       sendMessage():发送消息
    *       broadcast():广播消息
    *       addCount():操作count++，使用synchronized确保线程安全
    *       reduceCount():操作count--，使用synchronized确保线程安全
    * */
    private static Map<String,MyWebSocket> webSocketMap = new LinkedHashMap<>();
    private static int count=0;
    private Session session;
    private Logger log = LoggerFactory.getLogger(this.getClass());
    @OnOpen
    public void onOpen(Session session,@PathParam("userId") String userId){
        this.session=session;
        webSocketMap.put(userId,this);
        addCount();
        log.info("新的连接（{}）加入",userId);
    }
    /*
    * 制定消息格式
    * {
    *   send_user_id:-1,//发送者id
    *   sendUserInfo:{},//发送者的消息
    *   receive_type:'GROUP',//'GROUP'、'SINGLE'、'HALL'（群聊、单聊、大厅）
    *   receive_user_id:2,//发送给谁（SINGLE单聊必填）
    *   receive_group_id:111,//发送给群（GROUP群聊必填）
    *   message_str:'',//消息
    *   created_time_str:'',//时间
    * }
    * */
    @OnMessage
    public void onMessage(String message,Session session,@PathParam("userId") String userId){
        log.info("收到客户端（{}）的消息：{}",userId,message);
        try{
            JSONObject j= JSON.parseObject(message);
            j.put("send_user_id",Integer.parseInt(userId));
            Map<String, Object> map=new HashMap<>();
            map.put("id",Integer.parseInt(userId));
            List list=userService.selectUser(map);
            j.put("sendUserInfo",list.get(0));
            if("HALL".equals(j.get("receive_type").toString())){//大厅
                this.broadcast(j.toJSONString());
            }else if("GROUP".equals(j.get("receive_type").toString())){

            }else if("SINGLE".equals(j.get("receive_type").toString())){
//                this.sendMessage(j.toJSONString());
            }
            messageService.insertMessage(j);//将消息存放到消息表
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    @OnError
    public void onError(Throwable error,Session session,@PathParam("userId") String userId){
        log.info("（{}）发生错误,{}",userId,error.getMessage());
    }
    @OnClose
    public void onClose(@PathParam("userId") String userId){
        webSocketMap.remove(userId);
        reduceCount();
        log.info("（{}）连接关闭",userId);
    }
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }
    public static void broadcast(String message){
        MyWebSocket.webSocketMap.forEach((k,v)->{
            try{
                v.sendMessage(message);
            }catch (Exception e){
            }
        });
    }
    public static synchronized void addCount(){
        MyWebSocket.count++;
    }
    public static synchronized void reduceCount(){
        MyWebSocket.count--;
    }
}
